﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BlackBBS.Enums;
using BlackBBS.Infrastructure.Repository;
using BlackBBS.Extensions;

namespace BlackBBS.Models.Data
{
    [Serializable]
    public class User : ModelBase
    {
        public UserPreferences Preferences { get; set; }
        public Address Address { get; set; }
        public string Phone1 { get; set; }
        public string Phone2 { get; set; }
        public string Phone3 { get; set; }
        public Gender Gender { get; set; }
        public long GroupId { get; set; }
        public Group Group { get; set; }
        public bool IsLocked { get; set; }
        public string Login { get; set; }
        public string Firstname { get; set; }
        public string Lastname { get; set; }
        public string Password { get; set; }
        public string Email { get; set; }
        public string SysopNote { get; set; }
        public string PasswordHintQuestion { get; set; }
        public string PasswordHintAnswer { get; set; }
        public DateTime? Birthday { get; set; }
        public string BirthDate
        {
            get
            {
                if (this.Birthday == null)
                {
                    return "N/A";
                }
                return this.Birthday.Value.ToString("MM/dd/yyyy");
            }
        }
        public DateTime? Expires { get; set; }
        public int TimebankBalance { get; set; }
        public int TotalFilesUploaded { get; set; }
        public int TotalFilesDownloaded { get; set; }
        public int TotalExtProgramsOpened { get; set; }
        public int TotalMessages { get; set; }
        public int LoginFailures { get; set; }
        public int LoginTotal { get; set; }
        public DateTime? LoginFirst { get; set; }
        public DateTime? LoginLast { get; set; }
        public DateTime? LastNewFilesScan { get; set; }
        public DateTime Created { get; set; }
        public string Custom1 { get; set; }
        public string Custom2 { get; set; }
        public string Custom3 { get; set; }

        public User()
        {
        }

        internal override void Init()
        {
            base.Init();
            this.TemplateItems = new Dictionary<string, string>();
            this.TemplateItems.Add("${user.login}", "Login");
            this.TemplateItems.Add("${user.firstname}", "Firstname");
            this.TemplateItems.Add("${user.lastname}", "Lastname");
            this.TemplateItems.Add("${user.birthdate}", "BirthDate");

            this.TemplateItems.Add("${user.login.first}", "LoginFirst");
            this.TemplateItems.Add("${user.login.last}", "LoginLast");

            this.TemplateItems.Add("${user.total.files.uploaded}", "TotalFilesUploaded");
            this.TemplateItems.Add("${user.total.files.downloaded}", "TotalFilesDownloaded");
            this.TemplateItems.Add("${user.total.extprograms.opended}", "TotalExtProgramsOpened");
            this.TemplateItems.Add("${user.total.messages}", "TotalMessages");
            this.TemplateItems.Add("${user.total.failures}", "LoginFailures");
            this.TemplateItems.Add("${user.total.calls}", "LoginTotal");

        }

        public string FullName
        {
            get 
            {
                return string.Format("{0}{1}", this.Firstname, string.IsNullOrEmpty(this.Lastname) ? string.Empty : " " + this.Lastname);
            }
        }

        public override bool Equals(object obj)
        {
            if(obj == null)
            {
                return false;
            }
            User u = obj as User;
            if((System.Object)u == null)
            {
                return false;
            }
            return this.Login.Equals(u.Login);            
        }

        public override int  GetHashCode()
        {
 	         return this.Login.GetHashCode();
        }

        public bool AuthenticateUser(string password)
        {
            if (string.IsNullOrEmpty(password) || string.IsNullOrEmpty(this.Password))
            {
                return false;
            }
            return this.Password.Equals(password.Hash());
        }

        /// <summary>
        /// This is when the User has sucessfully logged in, increment counters, reset failures, etc.
        /// </summary>
        /// <param name="serverRepository">Active Server Repository</param>
        public void DoLoginEvents(IServerRepository serverRepository, string fromAddress)
        {
            this.LoginTotal++;
            this.LoginLast = DateTime.Now;
            serverRepository.Users.Save(this);

            serverRepository.CallHistories.Save(new CallHistory
            {
                UserId = this.Id,
                TimeLogin = this.LoginLast.Value,
                FromAddress = fromAddress
            });            

            // TODO; This data should be set before being saved to the DB on the User
            this.Preferences = new UserPreferences
            {
                TermHeight = 23,
                TermWidth = 80,
                ExpertMode = false
            };

            // TODO; This data should be set before being saved to the DB on the User
            this.Address = new Address
            {
                City = "Olathe",
                StateOrLocal = "KS"
            };

            // TODO get group for User
            this.Group = new Group
            {
                Level = 100
            };

        }

        public void SetPassword(string newPassword)
        {
            this.Password = newPassword.Hash();
        }

        public static User GetUserByLogin(IRepository<User> repository, string login)
        {
            if (string.IsNullOrEmpty(login))
            {
                return null;
            }
            var data = repository.GetAll().Where(x => x.Login.Equals(login));
            var result = data.LastOrDefault();
            if (result != null)
            {
                result.Init();
            }
            return result;
        }

    }
}
